package com.informatics.polymer.client.browserepository;

import org.restlet.gwt.Callback;
import org.restlet.gwt.Client;
import org.restlet.gwt.data.Form;
import org.restlet.gwt.data.MediaType;
import org.restlet.gwt.data.Method;
import org.restlet.gwt.data.Preference;
import org.restlet.gwt.data.Protocol;
import org.restlet.gwt.data.Request;
import org.restlet.gwt.data.Response;
import org.restlet.gwt.resource.Representation;
import org.restlet.gwt.resource.XmlRepresentation;

import com.google.gwt.user.client.Window;
import com.google.gwt.xml.client.NamedNodeMap;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.NodeList;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.FieldType;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.SelectionAppearance;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.Side;
import com.smartgwt.client.types.VisibilityMode;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLFlow;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.SectionStack;
import com.smartgwt.client.widgets.layout.SectionStackSection;
import com.smartgwt.client.widgets.tab.Tab;
import com.smartgwt.client.widgets.tab.TabSet;

/**
 * Class to build a panel to browse repeat units from a database.
 * 
 * @author ed
 * @version 1.0
 */
public class BrowseRepositoryPanel extends SectionStack {
	/**
	 * String array to retain all information found in the search.
	 */
	private String[] dataEntries;

	/**
	 * Create default panel.
	 */
	public BrowseRepositoryPanel() {
		setUpPanel();
	}

	/**
	 * Sets up the homopolymer panel system.
	 */
	public void setUpPanel() {
		this.setVisibilityMode(VisibilityMode.MULTIPLE);
		this.setWidth(1000);
		this.setHeight(500);
		this.setBorder("2px solid #458B00");
		SectionStackSection section1 = new SectionStackSection(
				"Browse the Repository");
		section1.setExpanded(true);
		HTMLFlow welcome = new HTMLFlow();
		welcome.setOverflow(Overflow.AUTO);
		welcome.setPadding(10);
		String welcomeString = "Welcome to the <I>\"Browse the Repository\"</I> panel, please see the instructions tab "
				+ "below for more details on how to view, add and delete repeat units.";
		welcome.setContents(welcomeString);
		section1.addItem(welcome);
		this.addSection(section1);
		this.setStyleName("sectionHeaderclosed");
		this.setBackgroundColor("#F0F0F0");
		// View section.
		SectionStackSection viewSection = new SectionStackSection("View");
		// Need listgrid here with id, picture and property data.
		final ListGrid browsingGrid = setUpListGrid4Browsing();
		// Actual call
		HLayout browseLayout = new HLayout();
		Button launchViewGridButton = new Button("Refresh Database");
		launchViewGridButton.setSize("200", "30");
		launchViewGridButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Request request = new Request(Method.GET,
						"http://localhost:8080/svc/viewRepository/");
				request.getClientInfo().getAcceptedMediaTypes().add(
						new Preference<MediaType>(MediaType.TEXT_PLAIN));
				new Client(Protocol.HTTP).handle(request, new Callback() {
					@Override
					public void onEvent(Request request, Response response) {
						dataEntries = response.getEntity().getText()
								.split("\n");
					}
				});
			}
		});
		Button viewDataBaseButton = new Button("View Database");
		viewDataBaseButton.setSize("200", "30");
		viewDataBaseButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
			}
		});
		browseLayout.addMember(launchViewGridButton);
		browseLayout.addMember(viewDataBaseButton);
		viewSection.addItem(browsingGrid);
		viewSection.addItem(browseLayout);
		String dataSourceLink = "<a href=\"http://localhost:8080/DataBaseDump.xml\">Database Source</a>";
		HTMLFlow dataSource = new HTMLFlow();
		dataSource.setContents(dataSourceLink);
		viewSection.addItem(dataSource);
		this.addSection(viewSection);
		// Add add repeat unit section.
		SectionStackSection addSection = new SectionStackSection(
				"Add Repeat Unit");
		addSection.addItem(jchemPaintPanel());
		// Need to add a jchem panel here with a submit/add button.
		this.addSection(addSection);
		// Add instructions section.
		SectionStackSection instructionSection = new SectionStackSection(
				"Instructions");
		instructionSection.setExpanded(false);
		HTMLFlow browseRepeatUnitInstructions = new HTMLFlow();
		browseRepeatUnitInstructions.setOverflow(Overflow.AUTO);
		browseRepeatUnitInstructions.setPadding(10);
		String instructions = "1. <b>Using the browsing panel</b><br></br> You can view, add and delete repeat unit structures.<br></br>"
				+ "To view our database of repeat units simple go to the \"<I>View</I>\" section and simply scroll down our table.<br></br>"
				+ "<b>Add Structures</b><br></br>To add structures simply draw structures into our chemical editor then click the add button.<br></br>"
				+ "<b>Delete Structures</b><br></br> In the  view section, simply click on the row that you want to delete then click the delete button, this will remove the structure from the database."
				+ "2.<b>Delete Panel</b><br></br> If you are not happy with your selection or choose to view another panel you can click on the <I>\"Delete Panel\"</I> and press the delete panel button"
				+ " this will delete the browse repository panel, so you can start over again.<br></br>";
		browseRepeatUnitInstructions.setContents(instructions);
		instructionSection.addItem(browseRepeatUnitInstructions);
		this.addSection(instructionSection);
		// Delete panel section
		SectionStackSection deletePanelSection = new SectionStackSection(
				"Delete Panel");
		deletePanelSection.setExpanded(false);
		Button deletePanelButton = new Button("Delete Panel!");
		deletePanelButton.setSize("100", "30");
		deletePanelButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				destroy();
			}
		});
		deletePanelSection.addItem(deletePanelButton);
		this.addSection(deletePanelSection);
	}

	/**
	 * TabSet panel for JChempaint
	 * 
	 * @return TabSet - tabs containing jchemPaint applets.
	 */
	private TabSet jchemPaintPanel() {
		TabSet drawingPanels = new TabSet();
		drawingPanels.setBackgroundColor("#F0F0F0");
		drawingPanels.setTabBarPosition(Side.TOP);
		drawingPanels.setWidth(1000);
		drawingPanels.setHeight(500);
		// Add separate panes.
		Tab tTab1 = new Tab("Draw Repeat Unit");
		Canvas tab1Canvas = new Canvas();
		tab1Canvas.setBackgroundColor("#F0F0F0");
		String appletCode = "<br></br>  <applet code=\"org.openscience.cdk.applications.jchempaint.applet.JChemPaintEditorApplet\" archive=\"jchempaint-applet-core.jar\" name=\"appletRUToAdd\" width=\"450\" height=\"375\">"
				+ "</applet>";
		tab1Canvas.setContents(appletCode);
		Button addRepeatUnitToDataBaseButton = new Button("Add New Repeat Unit");
		addRepeatUnitToDataBaseButton.setSize("300", "30");
		addRepeatUnitToDataBaseButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				int numberofRGroups = countNumberofFragmentPoints(
						callGetData(), "[Pr]");
				if (numberofRGroups == 2) {
					String smileStringToAdd = callGetData().replace("[Pr]",
							"[*]");
					Window.alert(smileStringToAdd);
					final Client client = new Client(Protocol.HTTP);
					Form form = new Form();
					form.add("repeatUnit", smileStringToAdd);
					Representation rep = form.getWebRepresentation();
					client.post("http://localhost:8080/svc/repeatUnitAddition",
							rep, new Callback() {
								@Override
								public void onEvent(Request request,
										Response response) {
									String resultantText = response.getEntity()
											.getText();
									com.google.gwt.user.client.Window
											.alert(resultantText);
								}
							});
				}
			}
		});
		// Restlet code to add repeat unit goest here
		tab1Canvas.addChild(addRepeatUnitToDataBaseButton);
		tTab1.setPane(tab1Canvas);
		drawingPanels.addTab(tTab1);
		return drawingPanels;
	}

	/**
	 * Native javascript method to invoke the DOM and extract smile strings from
	 * JchemPaint
	 * 
	 * @return String representation of the repeat unit.
	 */
	private native String callGetData() /*-{
		var smileString;
		smileString = $doc.appletRUToAdd.getSmiles();
		return smileString;
	}-*/;

	/**
	 * This method checks the number of R atoms drawn for the repeat units and
	 * end groups in JChempaint.
	 * 
	 * @param text
	 *            - R group value [R].
	 * @param search
	 *            - Smile string to search.
	 * @return - int value representing the number of R groups in a molecule.
	 */
	private int countNumberofFragmentPoints(final String text,
			final String search) {
		int count = 0;
		for (int fromIndex = 0; fromIndex > -1; count++) {
			fromIndex = text.indexOf(search, fromIndex + ((count > 0) ? 1 : 0));
		}
		return count - 1;
	}

	/**
	 * Constructs a listgrid to browse the repository.
	 * 
	 * @return ListGrid representation of all the data stored in the database.
	 */
	private ListGrid setUpListGrid4Browsing() {
		ListGrid fullRepositoryGrid = new ListGrid();
		fullRepositoryGrid.setSelectionType(SelectionStyle.SIMPLE);
		fullRepositoryGrid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
		fullRepositoryGrid.setPixelSize(500, 300);
		ListGridField idValue = new ListGridField("Id", "ID", 100);
		ListGridField structure = new ListGridField("URL",
				"Structure", 400);
		structure.setType(ListGridFieldType.IMAGE);
		structure.setImageHeight(200);
		structure.setImageWidth(400);
		ListGridField alogp = new ListGridField("ALOGP", "ALOGP", 100);
		ListGridField alogP2 = new ListGridField("AlogP2", "ALOGP2", 100);
		ListGridField amr = new ListGridField("AMR", "AMR", 100);
		ListGridField aPol = new ListGridField("APol", "APol", 100);
		ListGridField aromaticAtomCount = new ListGridField(
				"AromaticAtomCount", "AAC", 100);
		ListGridField aromaticBondCount = new ListGridField(
				"AromaticBondCount", "ABC", 100);
		ListGridField atomCount = new ListGridField("AtomCount", "AtomCount");
		ListGridField bondCount = new ListGridField("BondCount", "BondCount");
		ListGridField fragmentComplexity = new ListGridField(
				"FragmentComplexity", "FC", 100);
		ListGridField hbaCount = new ListGridField("HBACount", "HBA", 100);
		ListGridField hbdCount = new ListGridField("HBDCount", "HBD", 100);
		ListGridField kappa1 = new ListGridField("Kappa1", "Kappa1", 100);
		ListGridField kappa2 = new ListGridField("Kappa2", "Kappa2", 100);
		ListGridField kappa3 = new ListGridField("Kappa3", "Kappa3", 100);
		ListGridField ruleOf5 = new ListGridField("LipinskiRuleOf5Failures",
				"Lipinski", 100);
		ListGridField tpsa = new ListGridField("TPSA", "TPSA", 100);
		DataSource data = new DataSource(
				"http://localhost:8080/DataBaseDump.xml");
		data.setRecordXPath("/RepeatUnits/RepeatUnit");
		data.setDataFormat(DSDataFormat.XML);
		// Add datasource fields
		DataSourceField idDS = new DataSourceField("Id", FieldType.TEXT, "ID");
		DataSourceField structureImageDS = new DataSourceField("URL",
				FieldType.IMAGE, "Structure");
		DataSourceField alogPDS = new DataSourceField("ALOGP", FieldType.FLOAT,
				"ALOGP");
		DataSourceField alogp2DS = new DataSourceField("AlogP2",
				FieldType.FLOAT, "ALOGP2");
		DataSourceField aMRDS = new DataSourceField("AMR", FieldType.FLOAT,
				"AMR");
		DataSourceField apolDS = new DataSourceField("APol", FieldType.FLOAT,
				"APol");
		DataSourceField aromaticAtomsDS = new DataSourceField(
				"AromaticAtomCount", FieldType.INTEGER, "AAC");
		DataSourceField aromaticBondsDS = new DataSourceField(
				"AromaticBondCount", FieldType.INTEGER, "ABC");
		DataSourceField atomsDS = new DataSourceField("AtomCount",
				FieldType.INTEGER, "AtomCount");
		DataSourceField bondsDS = new DataSourceField("BondCount",
				FieldType.INTEGER, "BondCount");
		DataSourceField complexityDS = new DataSourceField(
				"FragmentComplexity", FieldType.FLOAT, "FC");
		DataSourceField hbaDS = new DataSourceField("HBACount",
				FieldType.INTEGER, "HBACount");
		DataSourceField hbdDS = new DataSourceField("HBDCount",
				FieldType.INTEGER, "HBDCount");
		DataSourceField kappa1DS = new DataSourceField("Kappa1",
				FieldType.FLOAT, "Kappa1");
		DataSourceField kappa2DS = new DataSourceField("Kappa2",
				FieldType.FLOAT, "Kappa2");
		DataSourceField kappa3DS = new DataSourceField("Kappa3",
				FieldType.FLOAT, "Kappa3");
		DataSourceField ruleOf5DS = new DataSourceField(
				"LipinskiRuleOf5Failures", FieldType.FLOAT, "Lipinski");
		DataSourceField tpsaDS = new DataSourceField("TPSA", FieldType.FLOAT,
				"TPSA");
		fullRepositoryGrid.setFields(idValue, structure, alogp, alogP2, amr,
				aPol, aromaticAtomCount, aromaticBondCount, atomCount,
				bondCount, fragmentComplexity, hbaCount, hbdCount, kappa1,
				kappa2, kappa3, ruleOf5, tpsa);
		fullRepositoryGrid.setDataSource(data);
		fullRepositoryGrid.setShowAllRecords(true);
		fullRepositoryGrid.fetchData();
		return fullRepositoryGrid;
	}
}
